import { compileToFunction } from "./compiler/index.js"
import { initLifeCycle, mountComponent } from "./lifeCycle.js"
import { defineReactive } from "./observe/index.js"
import Watcher, { nextTick } from "./observe/watcher.js"
import { initState } from "./state.js"

export function initMixin(Vue) {
  Vue.prototype._init = function (options) {
    let vm = this
    vm.$options = options

    // 初始化生命周期（部分）
    initLifeCycle(Vue)

    // 初始化状态
    initState(vm)


    // 处理template
    if (options.el) {
      vm.$mounted(options.el)
    }
  }

  Vue.prototype.$mounted = function (el) {
    let vm = this
    el = document.querySelector(el)
    if (!vm.$options.render) {
      // 获取template模板
      let template
      if (vm.$options.template && el) {
        template = vm.options.template
      } else {
        el && (template = el.outerHTML)
      }
      if (template) {
        vm.$options.render = compileToFunction(template)
        // console.log(vm.$options.render)
      }
    }

    // console.log(vm.$options.render)

    // 进行组件的挂载
    mountComponent(vm, el)
    // 生成render函数是为了有更好的性能，这样每次更新数据的时候，就只会触发render函数重新取得最新的数据渲染即可
    // 而不需要再次生成ast语法树
  }
}

export function initStateMixin(Vue) {
  Vue.prototype.$nextTick = nextTick

  // $set和$delete
  // 实现响应式修改删除
  Vue.prototype.$set = function (target, key, val) {
    target[key] = val
    defineReactive(target, key, val)
    // console.log(target)
    target.__ob__.dep.notify()
  }

  Vue.prototype.$delete = Vue.prototype.$del = function (target, key) {
    delete target[key]
    // console.log(target)
    target.__ob__.dep.notify()
  }

  Vue.prototype.$watch = function (expOrFn, cb, options) {
    let watcher = new Watcher(this, expOrFn, { user: true }, cb)
    console.log(watcher)
  }
}